package com.shermanzhou.nio;

import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * NIO 完成网络通信的三个核心：
 * 1. 通道（Channel）: 负责链接
 *     java.nio.channels.Channel 接口
 *          |-- SelectableChannel 抽象类
 *              |-- SocketChannel
 *              |-- ServerSocketChannel
 *              |-- DatagramChannel
 *
 *              |-- Pipe.SinkChannel
 *              |-- Pipe.SourceChannel
 *
 * 2. 缓冲区（Buffer）: 负责数据的存取
 * 3. 选择器（Selector) : 是 SelectableChannel 的多路复用器。用于监控 SelectableChannel 的 IO 状况。
 * @author zhouchaoqun
 * @date 2018/10/28 下午3:17
 */
public class BlockingNioTest {
    /**
     * 传输文件到服务器端（Blocking 模式）
     */
    @Test
    public void client() {
        SocketChannel socketChannel = null;
        FileChannel inChannel = null;
        try {
            //1. 创建 SocketChannel
            socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));

            //2. 创建一个 FileChannel
            inChannel = FileChannel.open(Paths.get("1.png"), StandardOpenOption.READ);

            //3. 分配一个缓冲区
            ByteBuffer byteBuffer = ByteBuffer.allocate(2048);

            //4. 发送数据
            while (inChannel.read(byteBuffer) != -1) {
                byteBuffer.flip();
                socketChannel.write(byteBuffer);
                byteBuffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (socketChannel != null) {
                try {
                    socketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (inChannel != null) {
                try {
                    inChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    @Test
    public void server() {
        ServerSocketChannel serverSocketChannel = null;
        FileChannel outChannel = null;
        SocketChannel socketChannel = null;
        try {
            //1. 创建 ServerSocketChannel
            serverSocketChannel = ServerSocketChannel.open();

            //2. 绑定端口
            serverSocketChannel.bind(new InetSocketAddress(9898));

            //3. 创建 FileChannel
            outChannel = FileChannel.open(Paths.get("3.png"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);

            //4. 获取客户端链接通道
            socketChannel = serverSocketChannel.accept();

            //5. 接收数据
            ByteBuffer byteBuffer = ByteBuffer.allocate(2048);
            while (socketChannel.read(byteBuffer) != -1) {
                byteBuffer.flip();
                outChannel.write(byteBuffer);
                byteBuffer.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (outChannel != null) {
                try {
                    outChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (socketChannel != null) {
                try {
                    socketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (serverSocketChannel != null) {
                try {
                    serverSocketChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }


    }
}
